Skip to content

Core: Stop fetchToken from sending the Authorization header#14552

Closed
okumin wants to merge 1 commit intoapache:mainfrom
okumin:oauth2-client-credentials
Closed

Core: Stop fetchToken from sending the Authorization header#14552
okumin wants to merge 1 commit intoapache:mainfrom
okumin:oauth2-client-credentials

Conversation

@okumin
Copy link
Contributor

@okumin okumin commented Nov 10, 2025

The current implementation stores the retrieved access token in AuthSession#headers, and the AuthSession and its headers are reused. This causes the OAuth2Manager sends an access token via the Authorization header as well as client ID and credential via the request-body at the next access token retrieval. I found Okta could not process such a request.

Reading RFC 6749, I guess we should have supported the basic auth. However, it is unclear all Iceberg environments can use the basic authentication anywhere. So, this pull request retains the policy by just removing the Authorization header from the token request.

Reproduction with curl

I would be able to successfully fetch an access token without the Authorization header.

% curl --request POST \
  --url "https://$OKTA_HOST/oauth2/$OKTA_APP_ID/v1/token" \
  --header 'accept: application/json' \
  --header 'cache-control: no-cache' \
  --header 'content-type: application/x-www-form-urlencoded' \
  --data "grant_type=client_credentials&scope=catalog&client_id=$CLIENT_ID&client_secret=$CLIENT_SECRET"
{"token_type":"Bearer","expires_in":3600,"access_token":"eyJraWQ...","scope":"catalog"}

However, with the Authorization header, Okta rejects a request.

% curl --request POST \
  --url "https://$OKTA_HOST/oauth2/$OKTA_APP_ID/v1/token" \
  --header 'accept: application/json' \
  --header 'authorization: Bearer yJraWQ...' \
  --header 'cache-control: no-cache' \
  --header 'content-type: application/x-www-form-urlencoded' \
  --data "grant_type=client_credentials&scope=catalog&client_id=$CLIENT_ID&client_secret=$CLIENT_SECRET"
{"errorCode":"invalid_client","errorSummary":"No client credentials found.","errorLink":"invalid_client","errorId":"oaeEin5lLeIRkeFNOSXPBrsLQ","errorCauses":[]}

This is the stacktrace I encountered.

Caused by: org.apache.iceberg.exceptions.RESTException: Unable to process: {"errorCode":"invalid_client","errorSummary":"No client credentials found.","errorLink":"invalid_client","errorId":"oaeFeryoPYSR8q6IDMlSqNVrA","errorCauses":[]}
	at org.apache.iceberg.rest.ErrorHandlers$OAuthErrorHandler.accept(ErrorHandlers.java:281)
	at org.apache.iceberg.rest.ErrorHandlers$OAuthErrorHandler.accept(ErrorHandlers.java:252)
	at org.apache.iceberg.rest.HTTPClient.throwFailure(HTTPClient.java:215)
	at org.apache.iceberg.rest.HTTPClient.execute(HTTPClient.java:299)
	at org.apache.iceberg.rest.BaseHTTPClient.postForm(BaseHTTPClient.java:111)
	at org.apache.iceberg.rest.auth.OAuth2Util.fetchToken(OAuth2Util.java:267)
	at org.apache.iceberg.rest.auth.OAuth2Util$AuthSession.fromCredential(OAuth2Util.java:709)
	at org.apache.iceberg.rest.auth.OAuth2Manager.newSessionFromCredential(OAuth2Manager.java:219)
	at org.apache.iceberg.rest.auth.OAuth2Manager.lambda$maybeCreateChildSession$2(OAuth2Manager.java:193)
	at com.github.benmanes.caffeine.cache.BoundedLocalCache.lambda$doComputeIfAbsent$14(BoundedLocalCache.java:2704)
	at java.base/java.util.concurrent.ConcurrentHashMap.compute(ConcurrentHashMap.java:1932)
	at com.github.benmanes.caffeine.cache.BoundedLocalCache.doComputeIfAbsent(BoundedLocalCache.java:2702)
	at com.github.benmanes.caffeine.cache.BoundedLocalCache.computeIfAbsent(BoundedLocalCache.java:2684)
	at com.github.benmanes.caffeine.cache.LocalCache.computeIfAbsent(LocalCache.java:112)
	at com.github.benmanes.caffeine.cache.LocalManualCache.get(LocalManualCache.java:63)
	at org.apache.iceberg.rest.auth.AuthSessionCache.cachedSession(AuthSessionCache.java:88)
	at org.apache.iceberg.rest.auth.OAuth2Manager.maybeCreateChildSession(OAuth2Manager.java:191)
	at org.apache.iceberg.rest.auth.OAuth2Manager.contextualSession(OAuth2Manager.java:140)
	at org.apache.iceberg.rest.auth.OAuth2Manager.contextualSession(OAuth2Manager.java:40)
	at org.apache.iceberg.rest.RESTSessionCatalog.loadInternal(RESTSessionCatalog.java:370)
	at org.apache.iceberg.rest.RESTSessionCatalog.loadTable(RESTSessionCatalog.java:397)
	at io.trino.plugin.iceberg.catalog.rest.TrinoRestCatalog.lambda$loadTable$0(TrinoRestCatalog.java:505)

@github-actions github-actions bot added the core label Nov 10, 2025
@okumin okumin force-pushed the oauth2-client-credentials branch from 3509194 to e56afb7 Compare November 11, 2025 08:11
@okumin okumin marked this pull request as ready for review November 11, 2025 09:29
@github-actions
Copy link

This pull request has been marked as stale due to 30 days of inactivity. It will be closed in 1 week if no further activity occurs. If you think that’s incorrect or this pull request requires a review, please simply write any comment. If closed, you can revive the PR at any time and @mention a reviewer or discuss it on the dev@iceberg.apache.org list. Thank you for your contributions.

@github-actions github-actions bot added the stale label Dec 12, 2025
@github-actions
Copy link

This pull request has been closed due to lack of activity. This is not a judgement on the merit of the PR in any way. It is just a way of keeping the PR queue manageable. If you think that is incorrect, or the pull request requires review, you can revive the PR at any time.

@github-actions github-actions bot closed this Dec 19, 2025
@yohanvalencia
Copy link

Will this be implemented? I'm having the same issues

@okumin
Copy link
Contributor Author

okumin commented Feb 9, 2026

@yohanvalencia I asked on Slack
https://apache-iceberg.slack.com/archives/C03LG1D563F/p1770643534180049

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants